package ar.com.ford.it.fullEconomics.persistence.dao;

import java.sql.Timestamp;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Vector;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc01Coststruct;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesg01Plant;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp01Part;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp02Commodity;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp03Commodpart;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp04Supply;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp06Mix;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp07Usage;
import ar.com.ford.it.fullEconomics.persistence.dto.Teess01Supplier;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.LogFactory;
import com.ford.it.persistence.PersistenceException;
import com.ford.it.persistence.PersistenceManager;
import com.ford.it.persistence.Query;
import com.ford.it.persistence.Transaction;

public class PartDao extends Dao {
    private static final String CLASS_NAME = PartDao.class.getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(
            CLASS_NAME);

    /**
     * Busca un part con un nombte especifico
     * 
     * @param part
     * Debe tener cargado el nombre del Part
     */

    public Teesp01Part findPartByPk(Teesp01Part part)
            throws PersistenceException {

        String METHOD_NAME = "findPartByPk";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesp01Part result = (Teesp01Part) this.getObjById(part);

        log.exiting(CLASS_NAME, METHOD_NAME);
        return result;
    }

    /**
     * Busca un part con un nombre especifico
     * 
     * @param part
     * Debe tener cargado el nombre del Part
     */

    public Collection<Teesp01Part> finLowCommodityParts(String lowCom,
                                                        Teesg01Plant plant)
            throws PersistenceException {

        String METHOD_NAME = "finLowCommodityParts";
        log.entering(CLASS_NAME, METHOD_NAME);

        Collection<Teesp01Part> resultCol = null;
        PersistenceManager pm = null;

        pm = PersistenceUtil.getPersistenceManager();
        Query query = pm.newQuery("findPartsByLowCommodity", Teesp01Part.class);
        query.setParameters(lowCom, plant);

        resultCol = (Collection) pm.executeQuery(query);

        log.exiting(CLASS_NAME, METHOD_NAME);
        return resultCol;
    }

    /**
     * Da de alta el Part pasado por parametro
     * 
     * @param part
     * Debe tener cargado el nombre del Part
     */
    public void createPart(Teesp01Part part) throws PersistenceException {

        String METHOD_NAME = "createPart";
        log.entering(CLASS_NAME, METHOD_NAME);

        Transaction tx = null;

        tx = PersistenceUtil.getTransaction();
        tx.registerInsert(part);

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Devuelve el part cuyo code es partCode listo para realizarle las
     * actualizaciones pertinentes
     * 
     * @param partCode
     * Code del Part a actualizar
     * @return
     * @throws PersistenceException
     */
    public Teesp01Part getPartForUpdate(String prefix, String base,
                                        String suffix, String partClass,
                                        Teesg01Plant plant)
            throws PersistenceException {

        String METHOD_NAME = "getPartForUpdate";
        log.entering(CLASS_NAME, METHOD_NAME);

        Teesp01Part result = null;
        Teesp01Part pk = new Teesp01Part();

        pk.setEesp01PartPrefixCodeC(prefix);
        pk.setEesp01PartBaseCodeC(base);
        pk.setEesp01PartSuffixCodeC(suffix);
        pk.setEesp01PartClassCodeC(partClass);
        pk.setEesp01PlantCodeC(plant);
        result = (Teesp01Part) super.getObjForUpdate(pk);

        log.exiting(CLASS_NAME, METHOD_NAME);
        return result;
    }

    /**
     * Elimina de forma definitiva de la base de datos el part pasado por
     * parametro
     * 
     * @param part
     * Debe haber sido obtenido de la base de datos
     */
    public void deletePart(Teesp01Part part) throws PersistenceException {

        String METHOD_NAME = "deletePart";
        log.entering(CLASS_NAME, METHOD_NAME);

        Transaction tx = PersistenceUtil.getTransaction();
        if (tx != null) {
            tx.registerDelete(part);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Busca Parts segun code
     * 
     * @param code
     * @return
     * @throws PersistenceException
     */
    public Collection<Teesp01Part> findParts(Teesp01Part part,
                                             Timestamp dateInMax,
                                             Timestamp dateOutMax)
            throws PersistenceException {

        String METHOD_NAME = "findParts";
        log.entering(CLASS_NAME, METHOD_NAME);

        Collection<Teesp01Part> resultCol = null;
        PersistenceManager pm = null;

        pm = PersistenceUtil.getPersistenceManager();
        Query query = pm.newQuery("findParts", Teesp01Part.class);
        query.setParameters(part, dateInMax, dateOutMax);

        resultCol = (Collection) pm.executeQuery(query);

        log.exiting(CLASS_NAME, METHOD_NAME);
        return resultCol;
    }

    /**
     * Busca Parts segun code
     * 
     * @param code
     * @return
     * @throws PersistenceException
     */
    public Collection<Teesp01Part> findParts(Teesp01Part part,
                                             Timestamp dateInMax,
                                             Timestamp dateOutMax,
                                             String supplierClass,
                                             String supplierCode)
            throws PersistenceException {

        String METHOD_NAME = "findParts";
        log.entering(CLASS_NAME, METHOD_NAME);

        Collection<Teesp04Supply> supplyCol = null;
        Collection<Teesp01Part> resultCol = new Vector<Teesp01Part>();
        PersistenceManager pm = null;
        Teesp04Supply supplyFind = new Teesp04Supply();
        Teess01Supplier supplier = new Teess01Supplier();
        
        supplier.setEess01SupplierClassCodeC(supplierClass);
        supplier.setEess01SupplierCodeC(supplierCode);
        supplier.setEess01LastUpdtS(dateOutMax);
        
        supplyFind.setTeess01Supplier(supplier);
        supplyFind.setTeesp01Part(part);
        supplyFind.setEesp04LastUpdtS(dateInMax);

        pm = PersistenceUtil.getPersistenceManager();
        Query query = pm.newQuery("findPartsBySupplier", Teesp04Supply.class);
        query.setParameters(supplyFind);

        supplyCol = (Collection) pm.executeQuery(query);
        for (Teesp04Supply supply : supplyCol)
            resultCol.add(supply.getTeesp01Part());

        log.exiting(CLASS_NAME, METHOD_NAME);
        return resultCol;
    }

    public boolean isDeleteable(Teesp01Part part) throws PersistenceException {

        String METHOD_NAME = "isDeleatable";
        log.entering(CLASS_NAME, METHOD_NAME);

        Collection<Teesp03Commodpart> commPartColl = null;
        Collection<Teesp06Mix> mixColl = null;
        Collection<Teesp07Usage> usageColl = null;
        Collection<Teesp04Supply> supplyColl = null;
        boolean isDel = false;
        PersistenceManager pm = null;
        pm = PersistenceUtil.getPersistenceManager();

        Query commPartsQuery = pm.newQuery("findCommodParts",
                Teesp03Commodpart.class);
        commPartsQuery.setParameters(part, "history");
        commPartColl = (Collection) pm.executeQuery(commPartsQuery);

        Query mixesQuery = pm.newQuery("findPartsMixes", Teesp06Mix.class);
        mixesQuery.setParameters(part);
        mixColl = (Collection) pm.executeQuery(mixesQuery);

        Query usageQuery = pm.newQuery("findPartsUsage", Teesp07Usage.class);
        usageQuery.setParameters(part);
        usageColl = (Collection) pm.executeQuery(usageQuery);

        Query supplyQuery = pm.newQuery("findPartsSupply", Teesp04Supply.class);
        supplyQuery.setParameters(part);
        supplyColl = (Collection) pm.executeQuery(supplyQuery);

        if (commPartColl.isEmpty() && mixColl.isEmpty() && usageColl.isEmpty()
                && supplyColl.isEmpty())
            isDel = true;

        log.exiting(CLASS_NAME, METHOD_NAME);
        return isDel;
    }

    /**
     * Elimina de forma definitiva de la base de datos el part pasado por
     * parametro y sus referencias
     * 
     * @param part
     * Debe haber sido obtenido de la base de datos
     */
    public void cascadeDelete(Teesp01Part part) throws PersistenceException {

        String METHOD_NAME = "deletePart";
        log.entering(CLASS_NAME, METHOD_NAME);

        Collection<Teesp03Commodpart> commPartColl = null;
        Collection<Teesp06Mix> mixColl = null;
        Collection<Teesp07Usage> usageColl = null;
        Collection<Teesp04Supply> supplyColl = null;
        Iterator<Teesp03Commodpart> commPartIter;
        Iterator<Teesp06Mix> mixIter;
        Iterator<Teesp07Usage> usageIter;
        Iterator<Teesp04Supply> supplyIter;
        PersistenceManager pm = null;
        pm = PersistenceUtil.getPersistenceManager();

        Query commPartsQuery = pm.newQuery("findCommodParts",
                Teesp03Commodpart.class);
        commPartsQuery.setParameters(part, "history");
        commPartColl = (Collection) pm.executeQuery(commPartsQuery);

        Query mixesQuery = pm.newQuery("findPartsMixes", Teesp06Mix.class);
        mixesQuery.setParameters(part);
        mixColl = (Collection) pm.executeQuery(mixesQuery);

        Query usageQuery = pm.newQuery("findPartsUsage", Teesp07Usage.class);
        usageQuery.setParameters(part);
        usageColl = (Collection) pm.executeQuery(usageQuery);

        Query supplyQuery = pm.newQuery("findPartsSupply", Teesp04Supply.class);
        supplyQuery.setParameters(part);
        supplyColl = (Collection) pm.executeQuery(supplyQuery);

        Transaction tx = PersistenceUtil.getTransaction();
        if (tx != null) {
            commPartIter = commPartColl.iterator();
            while (commPartIter.hasNext()) {
                tx.registerDelete(commPartIter.next());
            }
            mixIter = mixColl.iterator();
            while (mixIter.hasNext()) {
                tx.registerDelete(mixIter.next());
            }
            usageIter = usageColl.iterator();
            while (usageIter.hasNext()) {
                tx.registerDelete(usageIter.next());
            }
            supplyIter = supplyColl.iterator();
            while (supplyIter.hasNext()) {
                tx.registerDelete(supplyIter.next());
            }
            tx.registerDelete(part);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    public Collection<Teesp01Part> findPartsWithCostStructure(
                                                              Teess01Supplier supplier,
                                                              Teesp02Commodity commodity,
                                                              Teesp01Part part)
            throws PersistenceException {
        String METHOD_NAME = "findPartsWithCostStructure";
        log.entering(CLASS_NAME, METHOD_NAME);

        SupplyDao supplyDao = new SupplyDao();
        CommodityPartDao commPartDao = new CommodityPartDao();
        Collection<Teesp01Part> partColl = new LinkedList<Teesp01Part>();
        Collection<Teesc01Coststruct> costStrColl = null;
        PersistenceManager pm = null;

        pm = PersistenceUtil.getPersistenceManager();

        Query query = pm
                .newQuery("findCostStructures", Teesc01Coststruct.class);
        query.setParameters(supplier, null, part);
        costStrColl = (Collection) pm.executeQuery(query);

        for (Teesc01Coststruct costStr : costStrColl) {
            if (costStr.getTeesp02Commodity() != null)
                partColl.addAll(commPartDao.findCommodityParts(costStr
                        .getTeesp02Commodity()));
            else if (costStr.getTeesp04Supply() != null) {
                if(!partColl.contains(costStr.getTeesp04Supply().getTeesp01Part()))
                    partColl.add(costStr.getTeesp04Supply().getTeesp01Part());
            } else {
                Teesp04Supply supplyFind = new Teesp04Supply();
                supplyFind.setTeess01Supplier(costStr.getTeess01Supplier());
                Collection<Teesp04Supply> suppColl = supplyDao
                        .findSupply(supplyFind);
                for (Teesp04Supply supply : suppColl) {
                    if(!partColl.contains(supply.getTeesp01Part()))
                        partColl.add(supply.getTeesp01Part());
                }
            }
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return partColl;
    }
}
